package cn.gudian.cms.Upload

import javax.servlet.ServletContext
import org.springframework.web.multipart.MultipartHttpServletRequest
import org.springframework.web.multipart.commons.CommonsMultipartFile
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
import cn.gudian.cms.utils.UploadException
import cn.gudian.cms.utils.ImageUtil
import cn.gudian.cms.utils.DateUtil
import cn.gudian.cms.System.Sys

class UploadController {

  private static def noFile = ['html', 'htm', 'php', 'php2', 'php3', 'php4', 'php5', 'phtml', 'pwml', 'inc', 'asp', 'aspx', 'ascx', 'jsp', 'cfm', 'cfc', 'pl', 'bat', 'exe', 'com', 'dll', 'jar', 'vbs', 'js', 'reg', 'cgi', 'htaccess', 'asis', 'sh', 'shtml', 'shtm', 'phtm', 'jhtml', 'jhtm'];//定义不允许上传的文件类型

  private static def fileStandards = ["file": ["size": 1048576 * 30, "rootPath": "", "filePath": "uploads/File/", "domain": "", "ext": []],
          "img": ["size": 1048576 * 5, "rootPath": "", "filePath": "uploads/Image/", "domain": "", "ext": ['jpg', 'gif', 'jpeg', 'png']],
          "swf": ["size": 1048576 * 10, "rootPath": "", "filePath": "uploads/swf/", "domain": "", "ext": ['swf']],
          "flv": ["size": 1048576 * 30, "rootPath": "", "filePath": "uploads/Flv/", "domain": "", "ext": ['flv']],
          "media": ["size": 1048576 * 30, "rootPath": "", "filePath": "uploads/media/", "domain": "", "ext": ['mpg', 'mpeg', 'avi', 'wmv', 'asf', 'mov']],
  ]

  def index = {
    render("upload")
  }

  def file = {
    //安全性判断，未写
    String filesxml = upload((MultipartHttpServletRequest) request, fileStandards.get("file"));
    if (filesxml.indexOf("ERROR") == 0) {
      render filesxml
    } else {
      def filexml = new XmlSlurper().parseText(filesxml)
      def path
      def name
      filexml.uploadFile.each {
        path = it.@url.text()
        name = it.@name.text()
      }
      render """
           <script>history.back();parent.uploadSucceed('${name}','${path}');</script>
        """
    }
  }

  def flv = {
    //安全性判断，未写
    String filesxml = upload((MultipartHttpServletRequest) request, fileStandards.get("flv"));
    if (filesxml.indexOf("ERROR") == 0) {
      render filesxml
    } else {
      def filexml = new XmlSlurper().parseText(filesxml)
      def path
      def name
      filexml.uploadFile.each {
        path = it.@url.text()
        name = it.@name.text()
      }
      render """
           <script>parent.flvUploadSucceed('${name}','${path}');</script>
        """
    }
  }

  def img = {
    //安全性判断，未写
    String filesxml = upload((MultipartHttpServletRequest) request, fileStandards.get("img"));
    if (filesxml.indexOf("ERROR") == 0) {
      render """
           <script>parent.imgUploadFail('${filesxml}');</script>
      """
    } else {
      def filexml = new XmlSlurper().parseText(filesxml)
      def path
      def name
      filexml.uploadFile.each {
        path = it.@url.text()
        name = it.@name.text()
      }
      BufferedImage image = ImageIO.read(new File(servletContext.getRealPath(path)));
      //给图片加水印

      ImageUtil.waterMark(servletContext.getRealPath(path), servletContext.getRealPath(Sys.getValue("SITE_WATERIMG")), Sys.getValue("SITE_WATERPOSITION"));
      //  <script>history.back();parent.imgUploadSucceed('${name}','${path}');</script>
      render """
           <script>parent.imgUploadSucceed('${name}','${path}', '${image.getWidth()}','${image.getHeight()}');</script>

        """
    }
  }
  /**
   * 图片裁剪类
   imageSource=/uploads/Images/2010-04-03/201004031655110343.jpg  图片路径
   imageRotate=127  旋转角度
   viewPortW=400    观看窗口的宽度
   selectorY=125     可视窗口的X坐标
   selectorX=175       可视窗口X坐标
   viewPortH=300      观看窗口的高度
   selectorW=50       需要裁剪的的宽度
   selectorH=50        需要裁剪的的高度
   imageY=0     图片放大缩小相对于窗口的y值
   imageX=0    图片放大缩小相对于窗口的y值
   imageH=300         经过旋转缩放后的真实图片高度
   imageW=400         经过旋转缩放后的真实图片宽度
   action=imgCrop
   controller=upload
   */
  def imgCrop = {
    String returnInfo = "";
    Map cropImgMap = null;//裁切后的图片
    Map tempImgMap = null;//缩略图
    try {
      def imageSource = params.imageSource
      def imageRotate = Double.parseDouble(params.imageRotate)
      def viewPortW = Double.parseDouble(params.viewPortW)

      def selectorY = Double.parseDouble(params.selectorY)
      def selectorX = Double.parseDouble(params.selectorX)
      def viewPortH = Double.parseDouble(params.viewPortH)
      def selectorW = Double.parseDouble(params.selectorW)
      def selectorH = Double.parseDouble(params.selectorH)
      def imageX = Double.parseDouble(params.imageX)
      def imageY = Double.parseDouble(params.imageY)
      def imageH = Double.parseDouble(params.imageH)
      def imageW = Double.parseDouble(params.imageW)
      //获取原始图片的信息
      def fileRealPath = servletContext.getRealPath(imageSource);

      //获取新图片的高宽
      int newW = (int) imageW
      int newH = (int) imageH
      //改变图片的大小并且保存成新的图片,并且旋转图片
      if (imageRotate > 0 && imageRotate < 360) {
        tempImgMap = ImageUtil.scaleImg(fileRealPath, newW, newH, (int) imageRotate, "tmp_", 100, false);
      } else {
        tempImgMap = ImageUtil.scaleImg(fileRealPath, newW, newH, 0, "tmp_", 100, false);
      }
      //裁剪图片开始
      int x = 0;
      int y = 0;
      int w = (int) selectorW;
      int h = (int) selectorH;
      if (newW > viewPortW) {
        x = (int) selectorX
      } else {
        if (imageX >= 0 && (selectorX + selectorW) > imageX) {
          x = (int) selectorX < imageX ? 0 : (selectorX - imageX)
        } else if (imageX < 0 && (imageX + imageW) > selectorX) {
          x = (int) -imageX + selectorX
        }
      }
      if (newH > viewPortH) {
        y = (int) selectorY
      }
      else {
        if (imageY >= 0 && (selectorY + selectorH) > imageY) {
          y = (int) selectorY < imageY ? imageY : (selectorY - imageY)
        } else if (imageY < 0 && (imageY + imageH) > selectorY) {
          y = (int) -imageY + selectorY
        }
      }
      def returnMap = ImageUtil.cropImg(tempImgMap.get(ImageUtil.KEY_PATH), x, y, w, h, "crop_", 100, true);
      returnInfo = "/" + ImageUtil.realPathToUrl(returnMap.get("path"), getRootPath(servletContext), "");
    } catch (UploadException ue) {
      returnInfo = ue.message;
    }
    catch (Exception e) {
      e.printStackTrace();
      returnInfo = "ERROR 4008:file server error " + e.message;
    }
    finally {
      render returnInfo
    }

  }

 /** 上传所有文件的方法                                                                     */
  String upload(MultipartHttpServletRequest multiRequest, fileStandard) {
    String returnInfo = null;
    try {
      //得到上传的文件
      //CommonsMultipartFile orginalFile = (CommonsMultipartFile) multiRequest.getFile("myFile")
      def writer = new StringWriter()
      writer.append("<?xml version='1.0' encoding='utf-8'?>");
      def xmlSrc = new groovy.xml.MarkupBuilder(writer)
      Map files = multiRequest.getFileMap()
      xmlSrc.fileDefine() {
        //如果上传完毕
        files.each {
          CommonsMultipartFile orginalFile = (CommonsMultipartFile) it.value
          if (orginalFile) {
            // 获取原文件名称
            String originalFilename = orginalFile.getOriginalFilename()
            // 获取上传文件扩展名
            def extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1)?.toLowerCase();
            //文件的大小
            def fileSize = orginalFile.getSize();
            //判断是否是不允许上传的文件类型
            if (originalFilename.lastIndexOf(".") < 1 || extension in noFile) {
              //render("<script>parent.callback('不允许上传[${extension}]文件类型','','')</script>")
              throw new UploadException("ERROR : 不支持该格式文件上传： ${extension}");
            }
            if (fileStandard.get("ext").size() > 0 && !(extension in fileStandard.get("ext"))) {
              // render("<script>parent.callback('请上传${fileStandard.get("ext")}文件类型','','')</script>")
              throw new UploadException("ERROR : 只允许上传这些格式的文件： ${fileStandard.get("ext")}");
            }
            //判断上传文件大小
            /* if (fileSize > multiRequest.getParameter("maxSize")) {
              render("<script>parent.callback('文件大小超出限制最大支持"+(int)multiRequest.getParameter("maxSize")/1048576+"M','','')</script>")
              return
            }*/
            if (fileSize > fileStandard.get("size")) {
              // render("<script>parent.callback('文件大小超出限制最大支持"+(int)fileStandard.get("size")/1048576+"M','','')</script>")
              throw new UploadException("ERROR : 文件大小超出限制: " + (int) fileStandard.get("size") / 1048576 + "M");
            }

            //获取上传后的文件名称，使用当前时间表示
            def fileName = DateUtil.nowDateToString("yyyyMMddHHmmssSSSS");
            //获取上传后的文件夹名称，使用当前时间表示
            def folderName = DateUtil.nowDateToString("yyyy-MM-dd");
            //判断当前文件夹是否存在，不存在的话创建文件夹
            File folderFilePath = null;
            def newFileName = "${fileName}.${extension}"
            def newFileFolder = "${fileStandard.get("filePath")}${folderName}"
            //本域中上传
            if (fileStandard.get("rootPath") == "") {
              folderFilePath = new File(getRootPath(multiRequest.getSession().getServletContext()) + newFileFolder);
            }
            //跨域上传
            else {
              folderFilePath = new File("${fileStandard.get("rootPath")}${newFileFolder}");
            }

            if (!folderFilePath.exists()) {
              folderFilePath.mkdirs();
            }
            //上传文件
            orginalFile.transferTo(new File("${folderFilePath}/${newFileName}"))
            uploadFile(url: "${fileStandard.get("domain")}/${newFileFolder}/${newFileName}", name: originalFilename, size: fileSize)
          }
        }
      }
      returnInfo = writer.toString()
    }
    catch (UploadException ue) {
      returnInfo = ue.message;
    }
    catch (Exception e) {
      e.printStackTrace();
      returnInfo = "ERROR : 上传服务器出错： " + e.message;
    }
    finally {
      return returnInfo
    }

  }

  String getRootPath(ServletContext servletContext) {
    String realPath = servletContext.getRealPath("/");
    realPath = realPath.replaceAll("\\\\", "/");
    if (realPath.indexOf(realPath.length() - 1) != "/")
      return realPath + "/"
    else
      return realPath
  }

}
